

  module arm(
	clk,
	rst,
	IRQ,
	uart_rx,
	
	uart_tx
	);
	
	input 		clk;
	input 		rst;
	input 		IRQ;
	input		uart_rx;
	
	output 		uart_tx;
	
	wire 			irq;
	wire [31:0]	rom_data;
	wire [31:0]	ram_addr;
	wire 		ram_cen;
	wire [3:0]	ram_flag;
	wire [31:0]	ram_wdata;
	wire 		ram_wen;
	wire [31:0]	rom_addr;
	wire 		rom_en;
	wire [31:0]	ram_rdata_rom;
	wire [31:0]	ram_rdata_ram;
	wire 		rx_vld;
	wire [7:0]	rx_data;
	wire 		txrdy;
	
	reg [31:0]	ram_rdata;
	reg [3:0]	rd_sel;
	reg			tx_vld;
	reg [7:0]	tx_data;
	reg			irq_delay;
	
	always@(posedge clk or negedge rst)begin
		if(!rst)
			irq_delay <= 1'b1;
		else
			irq_delay <= IRQ;
	end
	  
	assign irq = irq_delay & ~IRQ;
	 
	arm_processor i_arm(  
          .clk                 (    clk                   ),
          .cpu_en              (    1'b1                  ),
          .cpu_restart         (    1'b0                  ),
          .fiq                 (    1'b0                  ),
          .irq                 (    irq                   ),
          .ram_abort           (    1'b0                  ),
          .ram_rdata           (    ram_rdata             ),
          .rom_abort           (    1'b0                  ),
          .rom_data            (    rom_data              ),
          .rst                 (    ~rst                   ),

          .ram_addr            (    ram_addr              ),
          .ram_cen             (    ram_cen               ),
          .ram_flag            (    ram_flag              ),
          .ram_wdata           (    ram_wdata             ),
          .ram_wen             (    ram_wen               ),
          .rom_addr            (    rom_addr              ),
          .rom_en              (    rom_en                )
        ); 
		  
	rom i_rom(
			.address_a				(		rom_addr[12:2]			),
			.address_b				(		ram_addr[12:2]			),
			.clock_a				(		clk						),
			.clock_b				(		clk						),
			.enable_a				(		rom_en					),
			.enable_b				(		ram_cen & ~ram_wen & (ram_addr[31:28] == 4'h0)),
			.q_a					(		rom_data					),
			.q_b					(		ram_rdata_rom			)
		);	
		
	ram i_ram0(
			.address				(		ram_addr[10:2]			),
			.clken					(		ram_cen & (ram_addr[31:28] == 4'h4) & ram_flag[0]),
			.clock					(		clk						),
			.data					(		ram_wdata[7:0]			),
			.wren					(		ram_wen					),
			.q						(		ram_rdata_ram[7:0]	)
		);
		
	ram i_ram1(
			.address				(		ram_addr[10:2]			),
			.clken					(		ram_cen & (ram_addr[31:28] == 4'h4) & ram_flag[1]),
			.clock					(		clk						),
			.data					(		ram_wdata[15:8]		),
			.wren					(		ram_wen					),
			.q						(		ram_rdata_ram[15:8]	)
		);
		
	ram i_ram2(
			.address				(		ram_addr[10:2]			),
			.clken					(		ram_cen & (ram_addr[31:28] == 4'h4) & ram_flag[2]),
			.clock					(		clk						),
			.data					(		ram_wdata[23:16]		),
			.wren					(		ram_wen					),
			.q						(		ram_rdata_ram[23:16]	)
		);
		
	ram i_ram3(
			.address				(		ram_addr[10:2]			),
			.clken					(		ram_cen & (ram_addr[31:28] == 4'h4) & ram_flag[3]),
			.clock					(		clk						),
			.data					(		ram_wdata[31:24]		),
			.wren					(		ram_wen					),
			.q						(		ram_rdata_ram[31:24]	)
		);
		
	rxtx i_uart(
			.clk					(		clk						),
			.rst					(		rst						),
      
			.tx						(		uart_tx					),
			.tx_vld					(		tx_vld					),
			.tx_data				(		tx_data					),
			.txrdy					(		txrdy						),
      
			.rx						(		uart_rx					),
			.rx_vld					(		rx_vld					),
			.rx_data				(		rx_data					)
  );
  
	always@(posedge clk or negedge rst)begin
		if(!rst)
			rd_sel <= 4'b1;
		else if(ram_cen & ~ram_wen)
			rd_sel <= {(ram_addr==32'he0000000),(ram_addr[31:28]==4'h0),(ram_addr[31:28]==4'h4)};
		else;
	end
	
	always@(*)begin
			case(rd_sel)
			3'b100:ram_rdata = txrdy ? 32'h0:32'h1;
			3'b010:ram_rdata = ram_rdata_rom;
			3'b001:ram_rdata = ram_rdata_ram;
			default:ram_rdata = ram_rdata_ram;
			endcase
	end
	
	always@(posedge clk or negedge rst)begin
		if(!rst)  
			tx_vld <= 1'b0;  
		else  
			tx_vld <= ram_cen & ram_wen & (ram_addr == 32'he0000004);  
	end  
	     
	always@(posedge clk or negedge rst)begin  
		if(!rst)  
			tx_data <= 8'h0;  
		else if( ram_cen & ram_wen & (ram_addr == 32'he0000004))  
			tx_data <= ram_wdata[7:0];  
		else; 
	end  
	  
endmodule   


